gdkevent: Hold refs to device/source_device
authorCarlos Garnacho <carlosg@gnome.org>
Mon, 3 Aug 2015 15:22:29 +0000 (17:22 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Wed, 19 Aug 2015 20:13:08 +0000 (22:13 +0200)
The extra reference will be held from GdkEventPrivate data, so there's
a common place to all events. Without this, events queued after devices/
capabilities disappear (eg. on TTY switch) might hold invalid pointers.
Windowing level operations on those devices (queries, grabs...) are
expected to fail at that time, but we should hold meaningful data for
the regular event handling paths.

https://bugzilla.gnome.org/show_bug.cgi?id=753185

gdk/gdkevents.c

index 2b2c6f8eec2d602fc3beacbde17c4b7388ada39a..4052d54bd8561fb7d5d98c7d0991bee00dce0bf4 100644 (file)
@@ -658,8 +658,8 @@ gdk_event_copy (const GdkEvent *event)
       GdkEventPrivate *private = (GdkEventPrivate *)event;
 
       new_private->screen = private->screen;
-      new_private->device = private->device;
-      new_private->source_device = private->source_device;
+      new_private->device = private->device ? g_object_ref (private->device) : NULL;
+      new_private->source_device = private->source_device ? g_object_ref (private->source_device) : NULL;
     }
 
   switch (event->any.type)
@@ -754,10 +754,18 @@ gdk_event_copy (const GdkEvent *event)
 void
 gdk_event_free (GdkEvent *event)
 {
+  GdkEventPrivate *private;
   GdkDisplay *display;
 
   g_return_if_fail (event != NULL);
 
+  if (gdk_event_is_allocated (event))
+    {
+      private = (GdkEventPrivate *) event;
+      g_clear_object (&private->device);
+      g_clear_object (&private->source_device);
+    }
+
   switch (event->any.type)
     {
     case GDK_KEY_PRESS:
@@ -1519,7 +1527,7 @@ gdk_event_set_device (GdkEvent  *event,
 
   private = (GdkEventPrivate *) event;
 
-  private->device = device;
+  g_set_object (&private->device, device);
 
   switch (event->type)
     {
@@ -1672,7 +1680,7 @@ gdk_event_set_source_device (GdkEvent  *event,
 
   private = (GdkEventPrivate *) event;
 
-  private->source_device = device;
+  g_set_object (&private->source_device, device);
 }
 
 /**